home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Modules
/
BackSpaceModules
/
Source
/
CreepyFace
/
CreepyFaceView.m
< prev
next >
Wrap
Text File
|
1994-03-23
|
8KB
|
416 lines
#import "CreepyFaceView.h"
#import <math.h>
#import "CFWireFrame.h"
#import <sys/dir.h>
#import <sys/types.h>
#import <objc/NXBundle.h>
@class CFWireFrame;
// this code is copyright Darcy Brockbank, 1993
//
// You may freely reuse and distribute this code in any way shape or
// form, provided that this notice stays intact.
//
// darcy@hasc.ca, samurai@cs.mcgill.ca
//
// StefView was implemented out of WorldSpaceView and retains some of the
// movement properties...
//
// The code for WorldSpaceView was written by Sam Streeper at CreepyFace, I think,
// and there were two other contributors, but I can't find their names in the
// source for it.
//
// CreepyFaceView shows a simple (ha!) spinning CreepyFace, in full 3D. The 3D code
// came from an app I wrote a long time ago called "CFWireFrame", and so the code
// is pretty scary. As well, this thing is only a quick hack, though a nice one.
//
// This thing has room for improvement, and if you do so, send me a copy!
//
// - darcy
@implementation CreepyFaceView
#define X_PERIOD 15000.0
#define Y_PERIOD 12000.0
#define DEFAULT_FPS 10
#define PI 3.1415926535
#define SIZE 256.0
#define MAX_IMAGE_WIDTH SIZE
#define MAX_IMAGE_HEIGHT SIZE
#define MAX_X_SPEED (26)
#define MAX_Y_SPEED (26)
#define BUFFER_WIDTH (MAX_IMAGE_WIDTH + MAX_X_SPEED + 1)
#define BUFFER_HEIGHT (MAX_IMAGE_HEIGHT + MAX_Y_SPEED + 1)
#define PRINT(a) printf(a)
#define MINX 0.0
#define MINY 0.0
#define ZOOM 680.0
- takeSpot:(float)x:(float)y;
{
[self draw];
return self;
}
- takeSnapshot;
{
return self;
}
- oneStep
{
NXRect black = {0,0,0,0};
NXRect ballRect;
BRECT new;
static float xdelt = 2.0;
static float ydelt = 2.0;
int changed = 0;
then = now;
now = currentTimeInMs();
xpos += xdelt;
if (xpos<MINX) {
xpos = MINX;
xdelt*=-1.0;
changed=1;
} else if (xpos>maxCoord.x){
xpos = maxCoord.x;
xdelt*=-1.0;
changed=1;
}
ypos += ydelt;
if (ypos<MINY) {
ypos = MINY;
ydelt*=-1.0;
changed=1;
} else if (ypos>maxCoord.y){
ypos = maxCoord.y;
ydelt*=-1.0;
changed=1;
}
if (changed){
#if 0
Axis flip[3]={y,y,y};
Direction dir[2]={positive,positive};
#else
Axis flip[3]={y,z,x};
Direction dir[2]={positive,negative};
#endif
axis = flip[axis];
spin = dir[spin];
}
new.l = floor(xpos);
new.b = floor(ypos);
new.r = new.l + imageSize.width;
new.t = new.b + imageSize.height;
ballRect.origin.x = 0;
ballRect.origin.y = 0;
ballRect.size.width = imageSize.width;
ballRect.size.height = imageSize.height;
redrawTo.x = MIN(new.l, old.l);
redrawTo.y = MIN(new.b, old.b);
redraw.origin.x = 0;
redraw.origin.y = 0;
redraw.size.width = (MAX(new.r, old.r)) - redrawTo.x + 1;
redraw.size.height = (MAX(new.t, old.t)) - redrawTo.y + 1;
black.size= redraw.size;
[buffer lockFocus];
PSsetgray(0);
NXRectFill(&black);
[self draw];
ballTo.x = new.l - redrawTo.x;
ballTo.y = new.b - redrawTo.y;
[buffer unlockFocus];
[buffer composite:NX_COPY toPoint:&redrawTo];
old = new;
return self;
}
- initFrame:(const NXRect *)frameRect
{
const char *animSpeed;
NXRect black = {0, 0, SIZE, SIZE };
imageSize = black.size;
[super initFrame:frameRect];
[self allocateGState]; // For faster lock/unlockFocus
[self setClipping:NO]; // even faster...
PSsetlinewidth(0.15);
backgroundColour=NX_COLORBLACK;
worldOrigin.x=0.0;
worldOrigin.y=0.0;
worldOrigin.z=0.0;
translationRate = 3.0;
currentZoom=ZOOM;
list = [[List alloc] init];
axis = y;
spin = positive;
buffer = [[NXImage alloc] initSize:&black.size];
if ([buffer lockFocus])
{
PSsetgray(0);
NXRectFill(&black);
[buffer unlockFocus];
}
animSpeed = NXGetDefaultValue([NXApp appName], "animSpeed");
if (animSpeed == NULL) framesPerSecond = DEFAULT_FPS;
else framesPerSecond = atoi(animSpeed);
nextRotationTime = 0;
[self newViewSize];
return self;
}
- sizeTo:(NXCoord)width :(NXCoord)height
{
[super sizeTo:width :height];
[self newViewSize];
return self;
}
- newViewSize
{
//this is called every time View size changes
NXRect black = {0, 0, BUFFER_WIDTH, BUFFER_HEIGHT };
then = now = currentTimeInMs();
if (oldSize.width == bounds.size.width &&
oldSize.height == bounds.size.height)
return self;
else
{
oldSize.width = bounds.size.width;
oldSize.height = bounds.size.height;
}
maxCoord.x = bounds.size.width - imageSize.width - MINX;
maxCoord.y = bounds.size.height - imageSize.height - MINY;
if (maxCoord.x < 0) maxCoord.x = 0;
if (maxCoord.y < 0) maxCoord.y = 0;
old.l = old.r = maxCoord.x/2 + MINX;
old.b = old.t = maxCoord.y/2 + MINY;
ballTo.x = ballTo.y = 0;
if ([buffer lockFocus])
{
PSsetgray(0);
NXRectFill(&black);
[buffer unlockFocus];
}
return self;
}
- (const char *)windowTitle
{
return "CreepyFaceView";
}
- inspector:sender
{
char buf[MAXPATHLEN];
if (!sharedInspectorPanel){
sprintf(buf,"%s/CreepyFaceView.nib",[sender moduleDirectory:"CreepyFace"]);
[NXApp loadNibFile:buf owner:self withNames:NO];
[self loadDir:[sender moduleDirectory:"CreepyFace"]];
}
return sharedInspectorPanel;
}
- tryToChangeCentre
{
id object=[self firstObject];
if (object) {
[object getCentre:&curOrigin.x:&curOrigin.y:&curOrigin.z];
} else {
curOrigin.x = curOrigin.y = curOrigin.z = 0.0;
}
return self;
}
- firstObject
{
return [list objectAt:0];
}
- free
{
[list free];
return [super free];
}
- (const char *)world;
{
return "CreepyFace.world";
}
- loadDir:(const char *)dir
{
char world[MAXPATHLEN+1];
sprintf(world,"%s/%s",dir,[self world]);
[self loadWorld:world];
[self tryToChangeCentre];
[self display];
return self;
}
- loadWorld:(const char *)world
{
DIR *dirp;
id newFrame;
struct direct *dp;
char *tail;
char temp[1024];
dirp=opendir(world);
if (!dirp) {
NXRunAlertPanel("Directory Error", "Can't read directory: %s","OK",0,0,world);
} else {
for(dp=readdir(dirp);dp!=NULL;dp=readdir(dirp)){
if ((tail=(rindex(dp->d_name,'.')))!=NULL){
if (strcmp((tail+1),"wireframe")==0){
sprintf(temp,"%s/%s",world,dp->d_name);
newFrame = [[CFWireFrame alloc] init];
[newFrame makeCFWireFrame:temp];
[self addThisObject:newFrame];
[newFrame translate:negative alongAxis:z atRate:1200];
}
if (strcmp((tail+1),"wireframeb")==0){
sprintf(temp,"%s/%s",world,dp->d_name);
newFrame = [[CFWireFrame alloc] init];
[newFrame readBinaryCodeFrom:temp];
[self addThisObject:newFrame];
[newFrame translate:negative alongAxis:z atRate:1200];
}
}
}
}
return self;
}
- setTranslationRate:sender;
{
translationRate=[sender floatValue];
return self;
}
- (int)numberOfObjects
{
return [list count];
}
- addThisObject:anObject
{
[list addObject:anObject];
return self;
}
- setZoom: sender
{
currentZoom=[sender floatValue];
[self display];
return self;
}
- draw;
{
int i,count = [list count] ;
for (i=0;i<count;i++){
id wireFrame = [list objectAt:i];
[wireFrame rotate:spin aroundAxis:axis atOrigin:curOrigin];
[wireFrame drawYourself:currentZoom
centeredOn:imageSize.width/2.0 :imageSize.height/2.0];
}
return self;
}
- translate:(Direction)dir alongAxis:(Axis)a atRate:(float)rate
{
int i,count = [list count];
for (i=0;i<count;i++){
[[list objectAt:i] translate:dir
alongAxis:a
atRate:rate];
}
[self tryToChangeCentre];
return self;
}
- rotate:(Direction)dir aroundAxis:(Axis)a atOrigin:(Origin)orig
{
int i,count = [list count];
for (i=0;i<count;i++){
[[list objectAt:i] rotate:dir
aroundAxis:a
atOrigin:orig];
}
return self;
}
- rotatey:sender;
{
[self rotate:negative aroundAxis:y atOrigin:curOrigin];
return self;
}
- rotateY:sender;
{
[self rotate:positive aroundAxis:y atOrigin:curOrigin];
return self;
}
- rotatez:sender;
{
[self rotate:negative aroundAxis:z atOrigin:curOrigin];
return self;
}
- rotateZ:sender;
{
[self rotate:positive aroundAxis:z atOrigin:curOrigin];
return self;
}
- rotatex:sender;
{
[self rotate:negative aroundAxis:x atOrigin:curOrigin];
return self;
}
- rotateX:sender;
{
[self rotate:positive aroundAxis:x atOrigin:curOrigin];
return self;
}
@end